﻿using Dora.Tools.Utility.Redis;
using Newtonsoft.Json;
using Surging.Core.Caching;
using Surging.Core.CPlatform;
using Surging.Core.CPlatform.Cache;
using Surging.Core.CPlatform.Routing;
using Surging.Core.ProxyGenerator;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Surging.Core.ApiGateWay.OAuth
{
    /// <summary>
    /// 授权服务提供者
    /// </summary>
    public class AuthorizationServerProvider : IAuthorizationServerProvider
    {
        private readonly IServiceProxyProvider _serviceProxyProvider;
        private readonly IServiceRouteProvider _serviceRouteProvider;
        private readonly CPlatformContainer _serviceProvider;
        private readonly ICacheProvider _cacheProvider;
        //private string BuildOuathService(string methodName) => $"{DoraServiceRoute.OauthRoutePath.IOauthService}{methodName}";
        public AuthorizationServerProvider(IServiceProxyProvider serviceProxyProvider
           , IServiceRouteProvider serviceRouteProvider
            , CPlatformContainer serviceProvider)
        {
            _serviceProvider = serviceProvider;
            _serviceProxyProvider = serviceProxyProvider;
            _serviceRouteProvider = serviceRouteProvider;
            _cacheProvider = CacheContainer.GetService<ICacheProvider>(AppConfig.CacheMode);
        }

        public async Task<string> GenerateTokenCredential(Dictionary<string, object> parameters)
        {
            string result = null;
            var payload = await _serviceProxyProvider.Invoke<object>(parameters, AppConfig.AuthorizationRoutePath, AppConfig.AuthorizationServiceKey);
           // IdentityUserDto userDto = await _serviceProxyProvider.Invoke<string>(parameters, AppConfig.AuthorizationRoutePath, AppConfig.AuthorizationServiceKey);
            //var userDto = await RemoteInvoke<IdentityUserDto>(BuildOuathService("GenerateTokenCredential")
            //    , new { userName = parameters["userName"].ToString(), pwd= parameters["pwd"].ToString(), systemKey = parameters["systemKey"].ToString() }, DoraModuleName.OAuthHost);
            if (payload != null && !payload.Equals("null"))
            {
                var jwtHeader = JsonConvert.SerializeObject(new JWTSecureDataHeader() { TimeStamp = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") });
                var base64Payload = ConverBase64String(JsonConvert.SerializeObject(payload));
                var encodedString = $"{ConverBase64String(jwtHeader)}.{base64Payload}";
                var route = await _serviceRouteProvider.GetRouteByPath(AppConfig.AuthorizationRoutePath);
                var signature = HMACSHA256(encodedString, route.ServiceDescriptor.Token);
                result = $"{encodedString}.{signature}";
                _cacheProvider.Add(base64Payload, result, AppConfig.AccessTokenExpireTimeSpan);
                //var jwtHeader = JsonConvert.SerializeObject(new JWTSecureDataHeader { TimeStamp = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") }); //生成token时间戳                

                //var encodedString =
                //    $"{ConvertHelper.ConverBase64String(jwtHeader)}.{ConvertHelper.ConverBase64String(userDto.Id.ToString())}"; //连接时间戳和dtunionid

                //const string sha256Secret = "sha256"; //读到h256签名私钥
                //var signature = ConvertHelper.HMACSHA256(encodedString, sha256Secret); //签名
                //var token = $"{encodedString}.{signature}"; //连接时间戳 user info 和签名
                ////存token及其它信息
                //if (parameters["systemKey"].ToString() == DoraSysIdentifier.TasMP.ToString())
                //{
                //    await TokenHelper.SaveTokenAsync(userDto.Id.ToString(), token, userDto, TimeSpan.FromMinutes(365 * 24 * 60));
                //}
                //else
                //{
                //    await TokenHelper.SaveTokenAsync(userDto.Id.ToString(), token, userDto, AppConfig.AccessTokenExpireTimeSpan);
                //}
                //Console.WriteLine(@"token已存入redis");
            }
            return result;
        }

        /// <summary>
        /// 根据token获取用户Id
        /// </summary>
        /// <returns></returns>
        public string GetPayloadString(string token)
        {
            //string result = null;
            //var jwtToken = token.Split('.');
            //if (jwtToken.Length == 3)
            //{

            //    result = Encoding.UTF8.GetString(Convert.FromBase64String(jwtToken[1]));
            //}
            //return result;
            return TokenHelper.Token2UserId(token);
        }

        /// <summary>
        /// 验证token合法性
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task<bool> ValidateClientAuthentication(string token)
        {
            //bool isSuccess = false;
            //var jwtToken = token.Split('.');
            //if (jwtToken.Length == 3)
            //{
            //    isSuccess = await _cacheProvider.GetAsync<string>(jwtToken[1]) == token;
            //}
            //return isSuccess;
            try
            {
                if (string.IsNullOrWhiteSpace(token))
                {
                    Console.WriteLine(@"client token is empty");
                    return false;
                }
                var jwtToken = token.Split('.');
                if (jwtToken.Length != 3)
                {
                    Console.WriteLine(@" token 格式错误" + token);
                    return false;
                }

                var userId = await TokenHelper.TokenPart2UserIdAsync(jwtToken[1]);
                var thisToken = await TokenHelper.GetTokenAsync(userId);
                if (string.IsNullOrWhiteSpace(thisToken))
                {

                    Console.WriteLine(@"服务器端没有查到token,token key is " + userId);
                    return false;
                }
                if (thisToken != token)
                {
                    Console.WriteLine($@"token key=={userId}");
                    Console.WriteLine($@"service token =={thisToken}");
                    Console.WriteLine($@"client token =={token}");
                    return false;
                }
                //刷新一次token,时长为半小时 
                _ = TokenHelper.ReFreshTokenAsync(userId, AppConfig.AccessTokenExpireTimeSpan);
                return true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            return false;
        }

        private string ConverBase64String(string str)
        {
            return Convert.ToBase64String(Encoding.UTF8.GetBytes(str));
        }

        private string HMACSHA256(string message, string secret)
        {
            secret = secret ?? "";
            byte[] keyByte = Encoding.UTF8.GetBytes(secret);
            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                return Convert.ToBase64String(hashmessage);
            }
        }
    }
}
